breaks_fun <- function(x) {
  if (max(x) > 10) {
    seq(0, 20, 4)
  } else if (max(x) > 5) {
    seq(-20, 20, 2) 
  }
  else if (max(x) < 1) {
    seq(-20,20,2)
  }
  else {
    seq(-20, 20, 1)
  }
}

coalesce_join <- function(x, y, 
                          by = NULL, suffix = c(".x", ".y"), 
                          join = dplyr::full_join, ...) {
 joined <- join(x, y, by = by, suffix = suffix, ...)
 # names of desired output
 cols <- union(names(x), names(y))
 
 to_coalesce <- names(joined)[!names(joined) %in% cols]
 suffix_used <- suffix[ifelse(endsWith(to_coalesce, suffix[1]), 1, 2)]
 # remove suffixes and deduplicate
 to_coalesce <- unique(substr(
  to_coalesce, 
  1, 
  nchar(to_coalesce) - nchar(suffix_used)
 ))
 
 coalesced <- purrr::map_dfc(to_coalesce, ~dplyr::coalesce(
  joined[[paste0(.x, suffix[1])]], 
  joined[[paste0(.x, suffix[2])]]
 ))
 names(coalesced) <- to_coalesce
 
 dplyr::bind_cols(joined, coalesced)[cols]
}


model.outcome <- function(fit, name) {
 
 fit <- fit$xsi[ order(row.names(fit$xsi)), ]
 estimates <- fit$xsi
 ses <- fit$se.xsi
 num_items <- length(estimates)/2
 cats <- paste(row.names(fit))[1:num_items]
 
 return(estimates %>% matrix(ncol = 2) %>% as.tibble() %>%
         transmute(diff = V1 - V2,
                   levels = cats) %>%
         bind_cols(ses %>% matrix(ncol = 2) %>% as.tibble() %>%
                    transmute(se = sqrt(V1^2 + V2^2),
                              model = name,
                              item = row_number())))
}

model.outcome_disc <- function(fit, name) {
 
 estimates <- fit$B[order(row.names(fit$B)), 2,]
 ses <- fit$se.B[order(row.names(fit$B)), 2,]
 num_items <- length(estimates)/2
 cats <- paste(row.names(fit))[1:num_items]
 
 return(estimates %>% matrix(ncol = 2) %>% as.tibble() %>%
         transmute(diff = V1 - V2,
                   levels = cats) %>%
         bind_cols(ses %>% matrix(ncol = 2) %>% as.tibble() %>%
                    transmute(se = sqrt(V1^2 + V2^2),
                              model = name,
                              item = row_number())))
}

clean_irt = function(model) {
  pattern = "([e|s])_([0-9]{1,2}).([[:word:]]+).([0-9]{1,2}|[[:word:]]+)"
  
  do.call(rbind, summary(model)$coefficients) %>% as.data.frame() %>%
  bind_cols(model = names(unlist(model$coefficients))) %>%
  mutate(language = recode_factor(str_match(model, pattern)[,2],
                                  e = "English", 
                                  s = "Spanish"),
         item = str_match(model, pattern)[,3],
         type = recode_factor(str_match(model, pattern)[,4],
                              Catgr = "Threshold", 
                              Dscr = "Discrimination"),
         level = glue('Y={number} vs. Y={number+1}', 
         number = as.numeric(str_match(model, pattern)[,5])),
         level_2 = glue('{number} vs. {number+1}', 
                      number = as.numeric(str_match(model, pattern)[,5])),
         level = plyr::mapvalues(level, "NA vs. NA", "Discrimination")) %>%
    as_tibble() -> df
    return(df)}

identify.anchor <-  function(data, model, language_var) {data %>%
    dplyr::filter(language_var == 1) %>%
    summarise(across(is.numeric, ~ as.numeric(.x > max(.x, na.rm = T)/2)))  %>%
    tam.mml(., irtmodel = model) %>%
    tam.se() -> fit
  
  estimates <- fit$xsi$est
  ses <- fit$xsi$se
  num_items <- length(estimates)/2
  
  return(estimates %>% matrix(ncol = 2) %>% as.tibble() %>%
           transmute(diff = V1 - V2) %>%
           bind_cols(ses %>% matrix(ncol = 2) %>% as.tibble() %>%
                       transmute(se = sqrt(V1^2 + V2^2))) )}

identify.anchor_2 <-  function(data, name, model = "2pl") {data %>%
    dplyr::summarise(dplyr::across(is.numeric, ~ as.numeric(.x > max(.x, na.rm = T)/2)))  %>%
    tam.mml(., irtmodel = model) %>%
    tam.se() -> fit

  estimates <- fit$xsi$est
  ses <- fit$xsi$se
  num_items <- length(estimates)/2
  
  return(estimates %>% matrix(ncol = 2) %>% as.tibble() %>%
           transmute(diff = V1 - V2) %>%
           bind_cols(ses %>% matrix(ncol = 2) %>% as.tibble() %>%
                       transmute(se = sqrt(V1^2 + V2^2),
                                 item = row_number(),
                                 name = name)) )}

identify.anchor.poly <-  function(data, model, language_var) {data %>%
    filter(language_var == 1) %>%
    tam.mml.2pl(., irtmodel = model) %>%
    tam.se() -> fit
  
  estimates <- fit$xsi$est
  ses <- fit$xsi$se
  num_items <- length(estimates)/2
  
  return(list(est = estimates %>% matrix(ncol = 2) %>% as.tibble() %>%
           transmute(diff = V1 - V2) %>%
           bind_cols(ses %>% matrix(ncol = 2) %>% as.tibble() %>%
                       transmute(se = sqrt(V1^2 + V2^2))),
           model = fit))}

clean_irt_2 = function(model) {
  
  summary(model)$coefficients %>% 
    as.tibble () %>% 
    bind_cols(model = row.names(summary(model)$coefficients)) %>% 
    mutate(language = recode_factor(str_match(model, "_([e|s])_")[,2], 
                                    e = "English", s = "Spanish"), 
           item = str_match(model, "([0-9]{1,2})")[,2], 
           type = recode_factor(str_match(model, "(Dffclt|Dscrmn)")[,2], 
                                Dffclt = "Threshold", 
                                Dscrmn = "Discrimination"), 
           level = "0/1") -> df
  
  return(df)
}

plot_irt = function(output, conditions, name) {output %>% 
    filter(type %in% conditions) %>%
    mutate(value = round(value, 1)) %>%
  ggplot(aes(y = value, x = forcats::fct_reorder(item, value), 
             color = language, group = language)) + 
  geom_errorbar(aes(ymin = value - 1.405*std.err, 
                    ymax = value + 1.405*std.err), 
   width = 0, size = 1.5, 
   position = position_dodge(.65)) + 
    geom_errorbar(aes(ymin = value - 1.96*std.err, 
                      ymax = value + 1.96*std.err), 
                  width = 0, 
                  size = .15, 
                  position = position_dodge(.65)) + 
    geom_errorbar(aes(ymin = value - .05*std.err, 
                      ymax = value + .05*std.err), 
                  width = 0, 
                  size = 4,
                  position = position_dodge(.65)) + 
  #geom_text(aes(label = value),
  #        position = position_dodge(.65),
  #color = "black", size = 2.5, alpha = .55) +
  facet_grid(. ~ level, 
             scales = "free", 
             space = "fixed") +
  theme_bw() + 
  theme(plot.title = element_text(hjust = 0.5)) + 
    coord_flip() + 
  scale_colour_grey(start = 0, end = .6) + 
  labs(title = name, x = "", 
       y = "Estimate", color = "Language") +
  theme_ipsum_rc() + 
    theme(panel.grid.minor = element_blank()) +
    coord_flip() +
    guides(color = guide_legend(reverse = TRUE)) +
    theme(text=element_text(size = 16),
          legend.position = "bottom") +
    scale_y_continuous(breaks = breaks_fun) +
    guides(color = guide_legend(reverse = TRUE))  -> p
  
  return(p)}

plot_irt_2 = function(output, conditions, name) {output %>% 
    filter(type %in% conditions) %>%
    ggplot(aes(y = value, x = forcats::fct_reorder(item, value), color = language)) + 
    geom_point(position = position_dodge(.65), size = 2) + 
    geom_hline(yintercept = 0, alpha = .10) + 
    geom_errorbar(aes(ymin = value - 1.405*std.err, 
                      ymax = value + 1.405*std.err), 
                  width = 0, size = 1.10, position = position_dodge(.65)) + 
    geom_errorbar(aes(ymin = value - 1.96*std.err, ymax = value + 1.96*std.err), 
                  width = 0, size = .5, position = position_dodge(.65)) + 
    facet_grid(. ~ type, scales = "free", space = "fixed") +
    theme_bw() + 
    theme(plot.title = element_text(hjust = 0.5)) + coord_flip() + 
    scale_colour_grey(start = .5, end = .2) + 
    theme(text = element_text(size=13), axis.text=element_text(size=8)) + 
    theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
    theme(legend.position = "bottom") + 
    labs(title = name, x = "Item", y = "Estimate", color = "Language") + 
    guides(color = guide_legend(reverse = TRUE)) -> p
  
  return(p)}

model.outcome_2 <- function(fit, name) {
  
  fit <- fit$xsi[ order(row.names(fit$xsi)), ]
  estimates <- fit$xsi
  ses <- fit$se.xsi
  num_items <- length(estimates)/2
  cats <- paste(row.names(fit))[1:num_items]
  
  return(estimates %>% matrix(ncol = 2) %>% as.tibble() %>%
           transmute(diff = V1 - V2,
                     levels = cats) %>%
           bind_cols(ses %>% matrix(ncol = 2) %>% as.tibble() %>%
                       transmute(se = sqrt(V1^2 + V2^2),
                                 model = name,
                                 item = row_number())))
}
